/*
 * Copyright (c) 2008, Xiong Yingfei, the University of Tokyo
 * All rights reserved.
 */
package ac.jp.u_tokyo.SyncLib.language3;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import ac.jp.u_tokyo.SyncLib.language.EvaluationFailedException;
import ac.jp.u_tokyo.SyncLib.language.GraphCombinatorBody;

public class Conjunction extends BracketSync
{
	private Set<Var> _vars = new HashSet<Var>();
	
	public void addVar(Var varName) {
		_vars.add(varName);
	}

	public Conjunction(int line)
	{
		super(line);
	}

	@Override
	public ac.jp.u_tokyo.SyncLib.language.SyncBody getBody(List<Var> imposedVars, Collection<String> genericParas)
			throws EvaluationFailedException
	{
		if (_vars.size() == 0 && _inners.size() == 1) {
			return _inners.iterator().next().getBody(imposedVars, genericParas);
		}
		
		GraphCombinatorBody result = new GraphCombinatorBody(getLine());
		result.addParameters(Helper.higherVar2LowerVar(imposedVars));
		addInner(genericParas, result);
		return result;
	}

	@Override
	public Set<Var> getVarUsed(Collection<String> genericParas)
			throws EvaluationFailedException
	{
	
		Set<Var> result = new HashSet<Var>();
		for(SyncConstruct body : _inners) {
			result.addAll(body.getVarUsed(genericParas));
		}
		for (Var v : _vars) {
			v.check(genericParas);
			result.remove(v);
		}
		return result;
	}

	@Override
	public void addBody(GraphCombinatorBody body, Collection<String> genericParas)
			throws EvaluationFailedException
	{
		if (_vars.size() == 0 && _inners.size() == 1) {
			_inners.iterator().next().addBody(body, genericParas);
		}

		
		GraphCombinatorBody result = new GraphCombinatorBody(getLine());
		Set<Var> parameters = getVarUsed(genericParas);
		result.addParameters(Helper.higherVar2LowerVar(parameters));
		addInner(genericParas, result);
		body.addConnection(body, result.getParameters());
	}

	private void addInner(Collection<String> genericParas,
			GraphCombinatorBody result) throws EvaluationFailedException
	{
		result.addOtherVars(Helper.higherVar2LowerVar(_vars));
		for (SyncConstruct s : _inners	) {
			s.addBody(result, genericParas);
		}
	}

}
